"""
Personality Traits and Cultural Dimensions for HDC-based encoding.

This module provides Big Five personality trait definitions, cultural dimension
encodings using Hofstede's framework, trait validation, normalization, and
relationship modeling using HDC operations.
"""

import numpy as np
import logging
from typing import Dict, List, Optional, Tuple, Union, Any
from dataclasses import dataclass, field
from enum import Enum
import scipy.stats as stats
from scipy.spatial.distance import cosine

from ..hdc.core import HDCOperations
from .models import (
    TraitType, CulturalDimension, BigFiveTraits, CulturalDimensions,
    ConfidenceScore
)

# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)


class TraitIntensity(Enum):
    """Enumeration of trait intensity levels."""
    VERY_LOW = 0.1
    LOW = 0.3
    MODERATE = 0.5
    HIGH = 0.7
    VERY_HIGH = 0.9


class TraitCorrelation(Enum):
    """Known correlations between personality traits."""
    POSITIVE_STRONG = 0.7
    POSITIVE_MODERATE = 0.4
    POSITIVE_WEAK = 0.2
    UNCORRELATED = 0.0
    NEGATIVE_WEAK = -0.2
    NEGATIVE_MODERATE = -0.4
    NEGATIVE_STRONG = -0.7


@dataclass
class TraitDefinition:
    """Definition structure for personality traits."""
    name: str
    description: str
    low_description: str
    high_description: str
    facets: List[str]
    typical_behaviors: List[str]
    measurement_methods: List[str]


@dataclass
class CulturalDimensionDefinition:
    """Definition structure for cultural dimensions."""
    name: str
    description: str
    low_description: str
    high_description: str
    measurement_indicators: List[str]
    cultural_examples: Dict[str, float]  # culture_name -> typical_score


class BigFiveTraitDefinitions:
    """
    Comprehensive definitions of Big Five personality traits.
    
    This class provides detailed definitions, descriptions, and behavioral
    indicators for each of the Big Five personality traits.
    """
    
    @staticmethod
    def get_openness_definition() -> TraitDefinition:
        """Get comprehensive definition of Openness to Experience."""
        return TraitDefinition(
            name="Openness to Experience",
            description="Tendency to be open to new aesthetic, cultural, or intellectual experiences",
            low_description="Conventional, down-to-earth, narrow interests, uncreative",
            high_description="Curious, broad interests, creative, original, imaginative, untraditional",
            facets=[
                "Ideas", "Fantasy", "Aesthetics", "Actions", "Feelings", "Values"
            ],
            typical_behaviors=[
                "Seeking new experiences", "Enjoying abstract thinking",
                "Appreciating art and beauty", "Being curious about many things",
                "Having vivid imagination", "Questioning authority and tradition"
            ],
            measurement_methods=[
                "NEO-PI-R questionnaire", "Big Five Inventory (BFI)",
                "Behavioral observation", "Creative task performance"
            ]
        )
    
    @staticmethod
    def get_conscientiousness_definition() -> TraitDefinition:
        """Get comprehensive definition of Conscientiousness."""
        return TraitDefinition(
            name="Conscientiousness",
            description="Tendency to be organized, responsible, and hardworking",
            low_description="Careless, disorganized, unreliable, lazy",
            high_description="Organized, responsible, reliable, hardworking, self-disciplined",
            facets=[
                "Competence", "Order", "Dutifulness", "Achievement Striving",
                "Self-Discipline", "Deliberation"
            ],
            typical_behaviors=[
                "Planning ahead", "Following through on commitments",
                "Being punctual", "Maintaining organized spaces",
                "Working systematically", "Persisting despite obstacles"
            ],
            measurement_methods=[
                "NEO-PI-R questionnaire", "Behavioral observation",
                "Task completion rates", "Goal achievement tracking"
            ]
        )
    
    @staticmethod
    def get_extraversion_definition() -> TraitDefinition:
        """Get comprehensive definition of Extraversion."""
        return TraitDefinition(
            name="Extraversion",
            description="Tendency to be outgoing, energetic, and sociable",
            low_description="Reserved, quiet, withdrawn, solitary, inhibited",
            high_description="Outgoing, energetic, sociable, assertive, talkative",
            facets=[
                "Gregariousness", "Assertiveness", "Activity", "Excitement Seeking",
                "Positive Emotions", "Warmth"
            ],
            typical_behaviors=[
                "Seeking social interaction", "Speaking up in groups",
                "Taking charge of situations", "Being energetic and active",
                "Expressing positive emotions", "Enjoying excitement and stimulation"
            ],
            measurement_methods=[
                "NEO-PI-R questionnaire", "Social interaction frequency",
                "Leadership behavior observation", "Communication patterns"
            ]
        )
    
    @staticmethod
    def get_agreeableness_definition() -> TraitDefinition:
        """Get comprehensive definition of Agreeableness."""
        return TraitDefinition(
            name="Agreeableness",
            description="Tendency to be cooperative, trustworthy, and sympathetic",
            low_description="Competitive, skeptical, tough-minded, antagonistic",
            high_description="Cooperative, trustworthy, empathetic, sympathetic, helpful",
            facets=[
                "Trust", "Straightforwardness", "Altruism", "Compliance",
                "Modesty", "Tender-Mindedness"
            ],
            typical_behaviors=[
                "Helping others", "Cooperating in groups",
                "Showing empathy and concern", "Avoiding conflict",
                "Being forgiving", "Trusting others' motives"
            ],
            measurement_methods=[
                "NEO-PI-R questionnaire", "Prosocial behavior observation",
                "Cooperation in game situations", "Peer ratings of helpfulness"
            ]
        )
    
    @staticmethod
    def get_neuroticism_definition() -> TraitDefinition:
        """Get comprehensive definition of Neuroticism."""
        return TraitDefinition(
            name="Neuroticism",
            description="Tendency to experience negative emotions and emotional instability",
            low_description="Calm, relaxed, unemotional, hardy, secure, self-satisfied",
            high_description="Anxious, nervous, emotional, insecure, inadequate, hypochondriacal",
            facets=[
                "Anxiety", "Angry Hostility", "Depression", "Self-Consciousness",
                "Impulsiveness", "Vulnerability"
            ],
            typical_behaviors=[
                "Worrying frequently", "Experiencing mood swings",
                "Feeling stressed easily", "Being self-critical",
                "Reacting strongly to setbacks", "Feeling overwhelmed by demands"
            ],
            measurement_methods=[
                "NEO-PI-R questionnaire", "Stress response measurement",
                "Emotional stability observation", "Anxiety and mood assessments"
            ]
        )


class CulturalDimensionDefinitions:
    """
    Comprehensive definitions of Hofstede's cultural dimensions.
    
    This class provides detailed definitions and cultural examples for each
    of Hofstede's cultural dimensions framework.
    """
    
    @staticmethod
    def get_power_distance_definition() -> CulturalDimensionDefinition:
        """Get definition of Power Distance dimension."""
        return CulturalDimensionDefinition(
            name="Power Distance",
            description="Extent to which less powerful members expect and accept unequal power distribution",
            low_description="Equality, decentralized power, accessible leadership",
            high_description="Hierarchy, centralized power, distant leadership",
            measurement_indicators=[
                "Hierarchy in organizations", "Authority respect",
                "Power concentration", "Status consciousness"
            ],
            cultural_examples={
                "Denmark": 0.18, "New Zealand": 0.22, "Germany": 0.35,
                "United States": 0.40, "France": 0.68, "China": 0.80,
                "Malaysia": 0.90
            }
        )
    
    @staticmethod
    def get_individualism_definition() -> CulturalDimensionDefinition:
        """Get definition of Individualism vs Collectivism dimension."""
        return CulturalDimensionDefinition(
            name="Individualism vs Collectivism",
            description="Degree to which individuals are integrated into groups",
            low_description="Collectivist, group loyalty, collective responsibility",
            high_description="Individualist, personal achievement, self-reliance",
            measurement_indicators=[
                "Group vs individual focus", "Loyalty expectations",
                "Decision-making style", "Responsibility attribution"
            ],
            cultural_examples={
                "Guatemala": 0.06, "China": 0.20, "South Korea": 0.18,
                "Japan": 0.46, "France": 0.71, "Germany": 0.67,
                "United States": 0.91, "Australia": 0.90
            }
        )
    
    @staticmethod
    def get_masculinity_definition() -> CulturalDimensionDefinition:
        """Get definition of Masculinity vs Femininity dimension."""
        return CulturalDimensionDefinition(
            name="Masculinity vs Femininity",
            description="Distribution of roles between genders and value emphasis",
            low_description="Feminine, cooperation, modesty, caring for weak",
            high_description="Masculine, competition, assertiveness, material success",
            measurement_indicators=[
                "Gender role differentiation", "Competition vs cooperation",
                "Achievement orientation", "Work-life balance values"
            ],
            cultural_examples={
                "Sweden": 0.05, "Norway": 0.08, "Denmark": 0.16,
                "Netherlands": 0.14, "France": 0.43, "United States": 0.62,
                "Germany": 0.66, "Japan": 0.95
            }
        )
    
    @staticmethod
    def get_uncertainty_avoidance_definition() -> CulturalDimensionDefinition:
        """Get definition of Uncertainty Avoidance dimension."""
        return CulturalDimensionDefinition(
            name="Uncertainty Avoidance",
            description="Society's tolerance for ambiguity and uncertainty",
            low_description="Comfortable with ambiguity, flexible, risk-taking",
            high_description="Need for structure, rules, predictability, risk-averse",
            measurement_indicators=[
                "Rule orientation", "Risk tolerance",
                "Structured vs flexible approaches", "Anxiety about unknown"
            ],
            cultural_examples={
                "Singapore": 0.08, "Denmark": 0.23, "United States": 0.46,
                "Germany": 0.65, "South Korea": 0.85, "France": 0.86,
                "Greece": 0.95
            }
        )
    
    @staticmethod
    def get_long_term_orientation_definition() -> CulturalDimensionDefinition:
        """Get definition of Long-term vs Short-term Orientation dimension."""
        return CulturalDimensionDefinition(
            name="Long-term vs Short-term Orientation",
            description="Focus on future vs past and present",
            low_description="Short-term, tradition, immediate results, stability",
            high_description="Long-term, adaptation, persistence, thrift",
            measurement_indicators=[
                "Planning horizon", "Tradition respect vs adaptation",
                "Persistence in achieving goals", "Thrift and savings"
            ],
            cultural_examples={
                "Philippines": 0.19, "United States": 0.26, "Germany": 0.83,
                "South Korea": 1.0, "China": 0.87, "Japan": 0.88
            }
        )
    
    @staticmethod
    def get_indulgence_definition() -> CulturalDimensionDefinition:
        """Get definition of Indulgence vs Restraint dimension."""
        return CulturalDimensionDefinition(
            name="Indulgence vs Restraint",
            description="Extent to which society allows free gratification of desires",
            low_description="Restrained, controlled desires, strict social norms",
            high_description="Indulgent, free gratification, optimistic attitude",
            measurement_indicators=[
                "Gratification control", "Social norms strictness",
                "Happiness and life satisfaction", "Freedom of expression"
            ],
            cultural_examples={
                "Pakistan": 0.0, "Egypt": 0.04, "Russia": 0.20,
                "Germany": 0.40, "United States": 0.68, "Sweden": 0.78,
                "Mexico": 0.97
            }
        )


class TraitValidator:
    """
    Validator for personality traits and cultural dimensions.
    
    This class provides methods for validating trait measurements,
    checking consistency, and ensuring data quality.
    """
    
    def __init__(self, hdc_ops: HDCOperations):
        """Initialize validator with HDC operations."""
        self.hdc_ops = hdc_ops
        self.trait_correlations = self._initialize_trait_correlations()
        self.cultural_correlations = self._initialize_cultural_correlations()
    
    def _initialize_trait_correlations(self) -> Dict[Tuple[str, str], float]:
        """Initialize known correlations between Big Five traits."""
        return {
            # Known empirical correlations from personality research
            ('openness', 'conscientiousness'): 0.02,
            ('openness', 'extraversion'): 0.27,
            ('openness', 'agreeableness'): 0.12,
            ('openness', 'neuroticism'): -0.01,
            ('conscientiousness', 'extraversion'): 0.16,
            ('conscientiousness', 'agreeableness'): 0.13,
            ('conscientiousness', 'neuroticism'): -0.32,
            ('extraversion', 'agreeableness'): 0.17,
            ('extraversion', 'neuroticism'): -0.07,
            ('agreeableness', 'neuroticism'): -0.24
        }
    
    def _initialize_cultural_correlations(self) -> Dict[Tuple[str, str], float]:
        """Initialize known correlations between cultural dimensions."""
        return {
            # Known correlations from Hofstede's research
            ('power_distance', 'individualism'): -0.68,
            ('power_distance', 'uncertainty_avoidance'): 0.28,
            ('individualism', 'masculinity'): 0.00,
            ('individualism', 'uncertainty_avoidance'): -0.31,
            ('masculinity', 'uncertainty_avoidance'): -0.14
        }
    
    def validate_big_five_traits(self, traits: BigFiveTraits) -> Tuple[bool, List[str]]:
        """
        Validate Big Five traits for consistency and plausibility.
        
        Args:
            traits: BigFiveTraits instance to validate
            
        Returns:
            Tuple of (is_valid, list_of_issues)
        """
        issues = []
        
        # Basic range validation
        if not traits.validate():
            issues.append("Trait values must be between 0.0 and 1.0")
            return False, issues
        
        # Check for extreme combinations that are unlikely
        trait_values = [
            traits.openness, traits.conscientiousness, traits.extraversion,
            traits.agreeableness, traits.neuroticism
        ]
        
        # Check if all traits are extremely high or low (unlikely profile)
        if all(v > 0.9 for v in trait_values):
            issues.append("All traits extremely high - unlikely personality profile")
        
        if all(v < 0.1 for v in trait_values):
            issues.append("All traits extremely low - unlikely personality profile")
        
        # Validate against known trait correlations
        correlation_issues = self._validate_trait_correlations(traits)
        issues.extend(correlation_issues)
        
        # Check confidence intervals are sensible
        ci_issues = self._validate_confidence_intervals(traits)
        issues.extend(ci_issues)
        
        return len(issues) == 0, issues
    
    def validate_cultural_dimensions(self, dimensions: CulturalDimensions) -> Tuple[bool, List[str]]:
        """
        Validate cultural dimensions for consistency and plausibility.
        
        Args:
            dimensions: CulturalDimensions instance to validate
            
        Returns:
            Tuple of (is_valid, list_of_issues)
        """
        issues = []
        
        # Basic range validation
        if not dimensions.validate():
            issues.append("Dimension values must be between 0.0 and 1.0")
            return False, issues
        
        # Validate against known cultural correlations
        correlation_issues = self._validate_cultural_correlations(dimensions)
        issues.extend(correlation_issues)
        
        return len(issues) == 0, issues
    
    def _validate_trait_correlations(self, traits: BigFiveTraits) -> List[str]:
        """Validate trait correlations against empirical norms."""
        issues = []
        trait_dict = {
            'openness': traits.openness,
            'conscientiousness': traits.conscientiousness,
            'extraversion': traits.extraversion,
            'agreeableness': traits.agreeableness,
            'neuroticism': traits.neuroticism
        }
        
        for (trait1, trait2), expected_correlation in self.trait_correlations.items():
            val1, val2 = trait_dict[trait1], trait_dict[trait2]
            
            # Convert to z-scores for correlation analysis
            val1_z = (val1 - 0.5) * 2  # Convert [0,1] to [-1,1]
            val2_z = (val2 - 0.5) * 2
            
            observed_pattern = val1_z * val2_z  # Positive if same direction
            
            # Check if correlation pattern matches expectation
            if expected_correlation > 0.3 and observed_pattern < -0.25:
                issues.append(
                    f"Unexpected negative pattern between {trait1} and {trait2} "
                    f"(expected positive correlation {expected_correlation:.2f})"
                )
            elif expected_correlation < -0.3 and observed_pattern > 0.25:
                issues.append(
                    f"Unexpected positive pattern between {trait1} and {trait2} "
                    f"(expected negative correlation {expected_correlation:.2f})"
                )
        
        return issues
    
    def _validate_cultural_correlations(self, dimensions: CulturalDimensions) -> List[str]:
        """Validate cultural dimension correlations against empirical norms."""
        issues = []
        dim_dict = {
            'power_distance': dimensions.power_distance,
            'individualism': dimensions.individualism,
            'masculinity': dimensions.masculinity,
            'uncertainty_avoidance': dimensions.uncertainty_avoidance,
            'long_term_orientation': dimensions.long_term_orientation,
            'indulgence': dimensions.indulgence
        }
        
        for (dim1, dim2), expected_correlation in self.cultural_correlations.items():
            val1, val2 = dim_dict[dim1], dim_dict[dim2]
            
            # Convert to z-scores for correlation analysis
            val1_z = (val1 - 0.5) * 2  # Convert [0,1] to [-1,1]
            val2_z = (val2 - 0.5) * 2
            
            observed_pattern = val1_z * val2_z  # Positive if same direction
            
            # Check if correlation pattern matches expectation
            if abs(expected_correlation) > 0.5:  # Strong correlation expected
                if expected_correlation > 0 and observed_pattern < -0.25:
                    issues.append(
                        f"Strong negative pattern between {dim1} and {dim2} "
                        f"(expected positive correlation {expected_correlation:.2f})"
                    )
                elif expected_correlation < 0 and observed_pattern > 0.25:
                    issues.append(
                        f"Strong positive pattern between {dim1} and {dim2} "
                        f"(expected negative correlation {expected_correlation:.2f})"
                    )
        
        return issues
    
    def _validate_confidence_intervals(self, traits: BigFiveTraits) -> List[str]:
        """Validate confidence intervals are sensible."""
        issues = []
        
        trait_cis = [
            ('openness', traits.openness, traits.openness_ci),
            ('conscientiousness', traits.conscientiousness, traits.conscientiousness_ci),
            ('extraversion', traits.extraversion, traits.extraversion_ci),
            ('agreeableness', traits.agreeableness, traits.agreeableness_ci),
            ('neuroticism', traits.neuroticism, traits.neuroticism_ci)
        ]
        
        for trait_name, value, (lower, upper) in trait_cis:
            if lower > upper:
                issues.append(f"{trait_name}: confidence interval lower bound > upper bound")
            
            if not (lower <= value <= upper):
                issues.append(f"{trait_name}: value {value:.2f} outside confidence interval [{lower:.2f}, {upper:.2f}]")
            
            if upper - lower > 0.8:  # Very wide CI
                issues.append(f"{trait_name}: confidence interval very wide ({upper-lower:.2f})")
        
        return issues


class TraitNormalizer:
    """
    Normalizer for personality traits and cultural dimensions.
    
    This class provides methods for normalizing trait measurements
    across different scales and measurement methods.
    """
    
    def __init__(self):
        """Initialize normalizer with standard parameters."""
        self.big_five_norms = self._initialize_big_five_norms()
        self.cultural_norms = self._initialize_cultural_norms()
    
    def _initialize_big_five_norms(self) -> Dict[str, Dict[str, float]]:
        """Initialize normative data for Big Five traits."""
        return {
            'openness': {'mean': 0.60, 'std': 0.15, 'min': 0.1, 'max': 0.95},
            'conscientiousness': {'mean': 0.55, 'std': 0.18, 'min': 0.05, 'max': 0.98},
            'extraversion': {'mean': 0.52, 'std': 0.20, 'min': 0.02, 'max': 0.98},
            'agreeableness': {'mean': 0.58, 'std': 0.16, 'min': 0.08, 'max': 0.95},
            'neuroticism': {'mean': 0.45, 'std': 0.22, 'min': 0.02, 'max': 0.95}
        }
    
    def _initialize_cultural_norms(self) -> Dict[str, Dict[str, float]]:
        """Initialize normative data for cultural dimensions."""
        return {
            'power_distance': {'mean': 0.50, 'std': 0.25},
            'individualism': {'mean': 0.45, 'std': 0.28},
            'masculinity': {'mean': 0.50, 'std': 0.20},
            'uncertainty_avoidance': {'mean': 0.55, 'std': 0.23},
            'long_term_orientation': {'mean': 0.50, 'std': 0.30},
            'indulgence': {'mean': 0.45, 'std': 0.25}
        }
    
    def normalize_raw_scores(self, raw_scores: Dict[str, float], 
                           score_type: str = 'big_five') -> Dict[str, float]:
        """
        Normalize raw trait scores to [0, 1] scale.
        
        Args:
            raw_scores: Dictionary of raw trait scores
            score_type: Type of scores ('big_five' or 'cultural')
            
        Returns:
            Dictionary of normalized scores
        """
        if score_type == 'big_five':
            norms = self.big_five_norms
        elif score_type == 'cultural':
            norms = self.cultural_norms
        else:
            raise ValueError(f"Unknown score type: {score_type}")
        
        normalized = {}
        for trait, raw_score in raw_scores.items():
            if trait not in norms:
                # Default normalization
                normalized[trait] = np.clip(raw_score, 0.0, 1.0)
                continue
            
            norm_data = norms[trait]
            
            # Z-score normalization then transform to [0,1]
            z_score = (raw_score - norm_data['mean']) / norm_data['std']
            
            # Convert z-score to percentile using normal CDF
            percentile = stats.norm.cdf(z_score)
            
            # Ensure within bounds
            if 'min' in norm_data and 'max' in norm_data:
                percentile = np.clip(percentile, norm_data['min'], norm_data['max'])
            else:
                percentile = np.clip(percentile, 0.0, 1.0)
            
            normalized[trait] = percentile
        
        return normalized
    
    def compute_trait_percentiles(self, traits: BigFiveTraits) -> Dict[str, float]:
        """Compute percentiles for Big Five traits."""
        trait_values = {
            'openness': traits.openness,
            'conscientiousness': traits.conscientiousness,
            'extraversion': traits.extraversion,
            'agreeableness': traits.agreeableness,
            'neuroticism': traits.neuroticism
        }
        
        percentiles = {}
        for trait, value in trait_values.items():
            norm_data = self.big_five_norms[trait]
            z_score = (value - norm_data['mean']) / norm_data['std']
            percentile = stats.norm.cdf(z_score) * 100
            percentiles[trait] = np.clip(percentile, 0, 100)
        
        return percentiles


class TraitRelationshipModeler:
    """
    Model relationships between personality traits using HDC operations.
    
    This class uses HDC vector operations to model complex relationships
    and interactions between different personality traits and cultural dimensions.
    """
    
    def __init__(self, hdc_ops: HDCOperations, dimension: int = 10000):
        """Initialize relationship modeler."""
        self.hdc_ops = hdc_ops
        self.dimension = dimension
        
        # Initialize relationship encoding vectors
        self._initialize_relationship_vectors()
    
    def _initialize_relationship_vectors(self):
        """Initialize vectors for encoding different types of relationships."""
        # Relationship type vectors
        self.relationship_vectors = {}
        
        relationship_types = [
            'synergy', 'opposition', 'compensation', 'amplification',
            'moderation', 'independence'
        ]
        
        for i, rel_type in enumerate(relationship_types):
            seed = hash(f"relationship_{rel_type}") % (2**31)
            self.relationship_vectors[rel_type] = self.hdc_ops.generate_random_vector(
                'bipolar'
            )
    
    def encode_trait_interaction(self, trait1_vector: np.ndarray, 
                               trait2_vector: np.ndarray,
                               relationship_type: str) -> np.ndarray:
        """
        Encode interaction between two traits.
        
        Args:
            trait1_vector: HDC vector for first trait
            trait2_vector: HDC vector for second trait
            relationship_type: Type of relationship ('synergy', 'opposition', etc.)
            
        Returns:
            HDC vector representing the trait interaction
        """
        if relationship_type not in self.relationship_vectors:
            raise ValueError(f"Unknown relationship type: {relationship_type}")
        
        # Get relationship encoding vector
        rel_vector = self.relationship_vectors[relationship_type]
        
        # Bind the two traits
        trait_combination = self.hdc_ops.binding(trait1_vector, trait2_vector)
        
        # Bind with relationship type
        interaction_vector = self.hdc_ops.binding(trait_combination, rel_vector)
        
        return interaction_vector
    
    def model_personality_profile_relationships(self, 
                                              trait_vectors: Dict[str, np.ndarray]) -> np.ndarray:
        """
        Model complex relationships within a complete personality profile.
        
        Args:
            trait_vectors: Dictionary mapping trait names to HDC vectors
            
        Returns:
            HDC vector representing profile-wide trait relationships
        """
        if len(trait_vectors) < 2:
            # Need at least 2 traits for relationships
            return np.zeros(self.dimension)
        
        relationship_vectors = []
        trait_names = list(trait_vectors.keys())
        
        # Model pairwise relationships
        for i, trait1 in enumerate(trait_names):
            for j, trait2 in enumerate(trait_names[i+1:], i+1):
                vec1, vec2 = trait_vectors[trait1], trait_vectors[trait2]
                
                # Determine relationship type based on traits
                rel_type = self._infer_relationship_type(trait1, trait2)
                
                # Encode the relationship
                relationship_vec = self.encode_trait_interaction(vec1, vec2, rel_type)
                relationship_vectors.append(relationship_vec)
        
        # Bundle all pairwise relationships
        if relationship_vectors:
            profile_relationships = self.hdc_ops.bundling(*relationship_vectors)
            return profile_relationships
        else:
            return np.zeros(self.dimension)
    
    def _infer_relationship_type(self, trait1: str, trait2: str) -> str:
        """Infer relationship type between two traits based on psychological theory."""
        # Known trait relationships from personality psychology
        synergy_pairs = [
            ('openness', 'extraversion'),
            ('conscientiousness', 'agreeableness'),
        ]
        
        opposition_pairs = [
            ('conscientiousness', 'neuroticism'),
            ('agreeableness', 'neuroticism'),
        ]
        
        amplification_pairs = [
            ('extraversion', 'agreeableness'),
        ]
        
        trait_pair = tuple(sorted([trait1, trait2]))
        
        if trait_pair in [tuple(sorted(pair)) for pair in synergy_pairs]:
            return 'synergy'
        elif trait_pair in [tuple(sorted(pair)) for pair in opposition_pairs]:
            return 'opposition'
        elif trait_pair in [tuple(sorted(pair)) for pair in amplification_pairs]:
            return 'amplification'
        else:
            return 'independence'  # Default for unknown relationships
    
    def analyze_trait_consistency(self, trait_vectors: Dict[str, np.ndarray]) -> float:
        """
        Analyze internal consistency of trait profile.
        
        Args:
            trait_vectors: Dictionary mapping trait names to HDC vectors
            
        Returns:
            Consistency score between 0.0 and 1.0
        """
        if len(trait_vectors) < 2:
            return 1.0  # Single trait is perfectly consistent
        
        # Compute pairwise similarities
        similarities = []
        trait_names = list(trait_vectors.keys())
        
        for i, trait1 in enumerate(trait_names):
            for j, trait2 in enumerate(trait_names[i+1:], i+1):
                vec1, vec2 = trait_vectors[trait1], trait_vectors[trait2]
                similarity = self.hdc_ops.cosine_similarity(vec1, vec2)
                similarities.append(abs(similarity))  # Use absolute value
        
        # Consistency is based on moderate inter-correlations
        # Too high = artificially similar, too low = incoherent
        mean_similarity = np.mean(similarities)
        
        # Optimal similarity range for personality traits (0.1 - 0.4)
        if 0.1 <= mean_similarity <= 0.4:
            consistency = 1.0
        elif mean_similarity < 0.1:
            # Too independent - reduce consistency
            consistency = mean_similarity / 0.1
        else:  # mean_similarity > 0.4
            # Too similar - reduce consistency
            consistency = max(0.0, 1.0 - (mean_similarity - 0.4) / 0.6)
        
        return consistency
    
    def compute_profile_stability(self, current_vectors: Dict[str, np.ndarray],
                                previous_vectors: Dict[str, np.ndarray]) -> float:
        """
        Compute temporal stability of personality profile.
        
        Args:
            current_vectors: Current trait vectors
            previous_vectors: Previous trait vectors for comparison
            
        Returns:
            Stability score between 0.0 and 1.0
        """
        if not previous_vectors:
            return 0.5  # No baseline for comparison
        
        # Compare common traits
        common_traits = set(current_vectors.keys()) & set(previous_vectors.keys())
        if not common_traits:
            return 0.0  # No common traits to compare
        
        stabilities = []
        for trait in common_traits:
            current_vec = current_vectors[trait]
            previous_vec = previous_vectors[trait]
            
            similarity = self.hdc_ops.cosine_similarity(current_vec, previous_vec)
            # Convert similarity to stability (high similarity = high stability)
            stability = (similarity + 1.0) / 2.0  # Convert from [-1,1] to [0,1]
            stabilities.append(stability)
        
        return np.mean(stabilities)